package com.bilibili.service.impl;

import com.bilibili.entity.User;
import com.bilibili.entity.UserInfo;
import com.bilibili.mapper.UserMapper;
import com.bilibili.service.UserInfoService;
import com.bilibili.service.UserService;
import com.bilibili.util.MD5Util;
import com.bilibili.util.ObjectUtil;
import com.bilibili.util.RSAUtil;
import com.bilibili.util.TokenUtil;
import io.mybatis.service.AbstractService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Optional;

@RequiredArgsConstructor
@Service
public class UserServiceImpl extends AbstractService<User, Long, UserMapper> implements UserService {

    private final UserInfoService userInfoService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String registerByPhone(String phone, String verifyCode) {
        Optional<User> userOptional = this.baseMapper.wrapper().eq(User::getPhone, phone).one();
        if (userOptional.isPresent()) {
            throw new RuntimeException("手机号已注册");
        }
        // TODO: 2024/2/4 添加验证码校验
        Date now = new Date();
        User register = new User();
        register.setPhone(phone);
        register.setCreateTime(now);
        register.setUpdateTime(now);
        this.baseMapper.insert(register);
        UserInfo userInfo = ObjectUtil.initUserInfo(register.getId());
        userInfoService.saveSelective(userInfo);
        return TokenUtil.generateToken(register.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String registerByEmail(String email, String verifyCode) {
        Optional<User> userOptional = this.baseMapper.wrapper().eq(User::getEmail, email).one();
        if (userOptional.isPresent()) {
            throw new RuntimeException("邮箱已注册");
        }
        // TODO: 2024/2/4 添加验证码校验
        Date now = new Date();
        User register = new User();
        register.setPhone(email);
        register.setCreateTime(now);
        register.setUpdateTime(now);
        this.baseMapper.insert(register);
        UserInfo userInfo = ObjectUtil.initUserInfo(register.getId());
        userInfoService.saveSelective(userInfo);
        return TokenUtil.generateToken(register.getId());
    }

    @Override
    public String login(String account, String password, String verifyCode, Integer type) {
        Optional<User> userOptional = this.baseMapper.wrapper().eq(User::getPhone, account).one();
        if (!userOptional.isPresent()) {
            throw new RuntimeException("账号或密码错误");
        }
        User user = userOptional.get();
        if (type == 1) {
            String decryptPassword = RSAUtil.decrypt(password);
            if (MD5Util.verify(decryptPassword, user.getPassword(), user.getSalt(), "UTF-8")) {
                throw new RuntimeException("账号或密码错误");
            }
        } else if(type == 2){
            if (!verifyCode.equals("123456")) {
                throw new RuntimeException("验证码错误");
            }
        } else {
            throw new RuntimeException("登录类型错误");
        }
        return TokenUtil.generateToken(user.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUser(User user) {
        this.baseMapper.updateByPrimaryKeySelective(user);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addPassword(Long id, String password, String confirmPassword) {
        Optional<User> userOptional = this.baseMapper.selectByPrimaryKey(id);
        if (!userOptional.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        String pas = RSAUtil.decrypt(password);
        String cfm = RSAUtil.decrypt(confirmPassword);
        if (!pas.equals(cfm)) {
            throw new RuntimeException("两次密码不一致");
        }
        String salt = String.valueOf(new Date().getTime());
        String passwordMD5 = MD5Util.sign(pas, salt, "UTF-8");
        User user = userOptional.get();
        User update = new User();
        update.setId(user.getId());
        update.setPassword(passwordMD5);
        update.setSalt(salt);
        update.setUpdateTime(new Date());
        this.baseMapper.updateByPrimaryKeySelective(update);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updatePassword(Long id, String oldPassword, String newPassword, String confirmPassword) {
        Optional<User> userOptional = this.baseMapper.selectByPrimaryKey(id);
        if (!userOptional.isPresent()) {
            throw new RuntimeException("用户不存在");
        }
        User user = userOptional.get();
        String oldPas = RSAUtil.decrypt(oldPassword);
        String salt = user.getSalt();
        String oldPasswordMD5 = MD5Util.sign(oldPas, salt, "UTF-8");
        if (!oldPasswordMD5.equals(user.getPassword())) {
            throw new RuntimeException("原密码错误");
        }
        String pas = RSAUtil.decrypt(newPassword);
        String cfm = RSAUtil.decrypt(confirmPassword);
        if (!pas.equals(cfm)) {
            throw new RuntimeException("两次密码不一致");
        }
        String passwordMD5 = MD5Util.sign(pas, salt, "UTF-8");

        User update = new User();
        update.setId(user.getId());
        update.setPassword(passwordMD5);
        update.setUpdateTime(new Date());
        this.baseMapper.updateByPrimaryKeySelective(update);
    }
}
